package ar.com.bdf.ipharma.protocolo.model;

import java.util.HashMap;
import java.util.Map;

import ar.com.bdf.ipharma.protocolo.model.exceptions.ParsingTramaException;
import ar.com.bdf.ipharma.protocolo.model.utils.ConverterUtil;


public class ParserTrama {
	
	private Map<String, Comando> comandos = new HashMap<String, Comando>();
	
	private static final String CRLF = "\r\n";
	
	public ParserTrama() {
		super();
		initialize();
	}

	private void initialize() {
		for (Comando comando : Comando.values()) {
			comandos.put(comando.toString(), comando);
		}
	}
	
	public String serializable(Trama trama){
		String longitud = ConverterUtil.convertToHexa(Math.round(trama.getLongitud() / 2));
		String comando = trama.getComando().toString();
		String checksum = trama.getCheckSum();
		String identificador;
		if (trama.getIdentificador() != null){
			identificador = ConverterUtil.convertToHexa(trama.getIdentificador());			
		}else{
			identificador = "";
		}
		return ":" + longitud + identificador + comando + trama.getDatos() + checksum	+ CRLF;
	}

	/**
	 * Retorna una trama determinada a partir del string, si el checksum no concuerda ahorra ParsingChecksumException
	 * @param serializable
	 * @return
	 */
	/**
	 * @param serializable
	 * @return
	 * @throws ParsingTramaException
	 */
	/**
	 * @param serializable
	 * @return
	 * @throws ParsingTramaException
	 */
	public Trama unserializable(String serializable) throws ParsingTramaException {
		if (serializable.length() < 11){
			throw new ParsingTramaException("No se puede parsear la trama debido a que no cumple con el largo minimo de 13 caracteres");
		}
		if (serializable.charAt(0) != ':'){
			throw new ParsingTramaException("No se puede parsear la trama ya que comienza por el caracter '" + serializable.charAt(0) + "' y no por el ':'");
		}
/*		if (!serializable.substring(serializable.length() - CRLF.length(),serializable.length()).equals(CRLF)){
			throw new ParsingTramaException("No se puede parsear la trama ya que no se ha finalizado correctamente con un CR/CL");
		};*/
		
		
		serializable = serializable.substring(1);
		serializable = serializable.substring(0, serializable.length() - 2);
		
		Integer longitudTramaSerializable = Integer.parseInt(serializable.substring(0, 2),16);
		
		
		Integer indexComando = 4; 

		String identificadorSerializable = serializable.substring(2, indexComando);
		Integer identificador;
		
		if (!identificadorSerializable.equalsIgnoreCase("FF")){
			identificador = Integer.parseInt(identificadorSerializable, 16);
		}else{
			indexComando = 2;
			identificador = null;
		}
			
		Comando comando = comandos.get(serializable.substring(indexComando, indexComando + 2));
		String datos = serializable.substring(indexComando + 2, serializable.length() - 2);
		
		
		DataTrama data = new DataTrama(identificador);
		Trama trama = new Trama(data, comando, datos);

		Integer longitudRealTrama = trama.getLongitud();
		
		if (!longitudRealTrama.equals(longitudTramaSerializable * 2)){
			throw new ParsingTramaException("No coincide la longitud de la trama, esperado:" + longitudTramaSerializable + "; longitud real:" + longitudRealTrama);
		}
		
		String checksum = serializable.substring(serializable.length() - 2);
		
		if (!trama.getCheckSum().equals(checksum)){
			throw new ParsingTramaException("No coincide el checksum de la trama, esperado:" + trama.getCheckSum() + "; checksum real:" + checksum);
		}
		
		return trama;
	}
	
	

}
